package pl.edu.pw.perg.compinfodb.datamodel;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;

import pl.edu.pw.perg.compinfodb.entities.ElementType;
import pl.edu.pw.perg.compinfodb.entities.VirtualElement;
import pl.edu.pw.perg.compinfodb.manager.IElementTypeManager;

@SuppressWarnings("serial")
public class TypeTreeModel extends DefaultTreeModel implements TreeModel,
		TreeSelectionListener {

	private ElementType selectedElement;
	private List<IElementTypeSelectionListener> listeners = new ArrayList<IElementTypeSelectionListener>();

	public TypeTreeModel(IElementTypeManager typeManager, boolean cable) {
		super(getTree(typeManager, cable));
	}

	private static TreeNode getTree(IElementTypeManager typeManager,
			boolean cable) {
		return cable? getCablesTree(typeManager) : getModulesTree(typeManager);
	}

	private static SelectableTreeNode createTree(ElementType elt) {
		SelectableTreeNode rootNode = new SelectableTreeNode(elt);
		Collection<ElementType> children = elt.getChildren();
		for (Iterator<ElementType> i = children.iterator(); i.hasNext();) {
			ElementType child = (ElementType) i.next();
			rootNode.add(createTree(child));
		}
		return rootNode;

	}

	private static SelectableTreeNode getStructureTree(
			IElementTypeManager elementManager) {
		SelectableTreeNode rootNode = new SelectableTreeNode("CMS Experiment");
		List<ElementType> elements = elementManager.findRoots();
		Collections.sort(elements);
		for (Iterator<ElementType> i = elements.iterator(); i.hasNext();) {
			ElementType elt = (ElementType) i.next();
			SelectableTreeNode eltNode = createTree(elt);
			rootNode.add(eltNode);
		}
		ElementType allEt = new ElementType();
		allEt.setTypeName("ALL");
		SelectableTreeNode all = new SelectableTreeNode(allEt);
		rootNode.add(all );
		return rootNode;
	}
	
	private static SelectableTreeNode getCablesTree(
			IElementTypeManager elementManager) {
		SelectableTreeNode rootNode = new SelectableTreeNode("CMS Experiment");
		List<ElementType> elements = elementManager.findRootCables();
		Collections.sort(elements);
		for (Iterator<ElementType> i = elements.iterator(); i.hasNext();) {
			ElementType elt = (ElementType) i.next();
			SelectableTreeNode eltNode = createTree(elt);
			rootNode.add(eltNode);
		}
		return rootNode;
	}
	
	private static SelectableTreeNode getModulesTree(
			IElementTypeManager elementManager) {
		SelectableTreeNode rootNode = new SelectableTreeNode("CMS Experiment");
		List<ElementType> elements = elementManager.findRootModules();
		Collections.sort(elements);
		for (Iterator<ElementType> i = elements.iterator(); i.hasNext();) {
			ElementType elt = (ElementType) i.next();
			SelectableTreeNode eltNode = createTree(elt);
			rootNode.add(eltNode);
		}
		return rootNode;
	}
	
	public void addElementTypeSelectionListener(IElementTypeSelectionListener l){
		listeners.add(l);
	}

	public void valueChanged(TreeSelectionEvent e) {
		SelectableTreeNode selectedNode = (SelectableTreeNode) ((JTree) e
				.getSource()).getLastSelectedPathComponent();
		if (selectedNode == null)
			return;
		Object element = selectedNode.getUserObject();
		if (element instanceof ElementType)
			selectedElement = (ElementType) element;
		for (IElementTypeSelectionListener l : listeners) {
			l.selectionChanged(selectedElement);
		}
	}
}
